package com.boot.security.server.service.impl.mffl.WXPay;

import com.boot.security.server.dao.mffl.MfflOrderDao;
import com.boot.security.server.dao.mffl.MfflRefundDao;
import com.boot.security.server.dto.LoginUser;
import com.boot.security.server.model.SysUser;
import com.boot.security.server.model.mffl.MfflOrder;
import com.boot.security.server.model.mffl.MfflRefund;
import com.boot.security.server.utils.UserUtil;
import com.boot.security.server.utils.mffl.ProjectUtil;
import com.boot.security.server.utils.mffl.ReturnBean;
import com.boot.security.server.utils.mffl.WecahtPayUtil.OurWxPayConfig;
import com.boot.security.server.utils.mffl.WecahtPayUtil.WechatPay;
import com.boot.security.server.utils.mffl.WecahtPayUtil.WxpayParam;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 微信支付
 */
@Service
public class WXPayService {
    //订单
    @Autowired
    private MfflOrderDao mfflOrderDao;

    //回调ip地址
    @Value("${Pay.NotifyIP}")
    public String NotifyIP;

    //配置过期秒数
    @Value("${Pay.payConfirmSeconds}")
    private Integer payConfirmSeconds;

    //配置微信支付随机数
    @Value("${Pay.attach}")
    private String attach;


    //退款表
    @Autowired
    MfflRefundDao mfflRefundDao;

    //redis
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    //微信支付
    @Autowired
    WechatPay wechatpay;

    /**
     * 微信支付
     *
     * @param Notifyurl         回调地址（开头带斜杠”\“）
     * @param Body              服务名称
     * @param payMerchantNumber 商户订单号
     * @return APP所用拉起支付所用信息
     */
    public ReturnBean WXPay(String Notifyurl, String Body, String payMerchantNumber) {
        ReturnBean returnBean = new ReturnBean();

        //查看订单中是否存在该订单
        MfflOrder MfflOrder = mfflOrderDao.getBypaymerchantnumber(payMerchantNumber);
        if (MfflOrder == null) {
            returnBean.setReturnBean("106");
            return returnBean;
        }
        if (MfflOrder.getState() == 1) {
            returnBean.setReturnBean("113");
            return returnBean;
        }
        if (MfflOrder.getState() == 2) {
            returnBean.setReturnBean("114");
            return returnBean;
        }

        Map<String, String> map = null;
        //微信支付参数
        WxpayParam wxpayParam = new WxpayParam();
        wxpayParam.setNotify_url(NotifyIP + Notifyurl);//回调地址
        wxpayParam.setSpbill_create_ip("100.65.31.151");                        //终端IP
        wxpayParam.setBody(Body);                                               //商品描述
        wxpayParam.setTotal_fee(MfflOrder.getMoney().toString());               //商品金额
        wxpayParam.setPayMerchantNumber(MfflOrder.getPayMerchantNumber());      //商户订单号
        wxpayParam.setNonce_str(ProjectUtil.getRandom(10));//随机数
        wxpayParam.setAttach(attach);   //附加信息
        WechatPay wechatPay = new WechatPay();
        try {
            map = wechatPay.GetPayOrder(wxpayParam);
            if (map.size() == 0) {
                returnBean.setReturnBean("123");
                return returnBean;
            }
            returnBean.setDatas(map);
        } catch (Exception e) {
            if (e.getMessage().equals("订单已支付，无需重复支付")) {
                returnBean.setReturnBean("126");
                return returnBean;
            }
            e.printStackTrace();
        }
        return returnBean;
    }


    /**
     * 微信退款
     *
     * @param payMerchantNumber 退款商户单号
     * @param refundfee         实际退款金额
     * @param refundreason      退款理由
     * @param identity          身份0前台 1后台
     * @return
     * @throws Exception
     */
    @Transactional
    public ReturnBean weChatrefund(String payMerchantNumber, String refundfee, String refundreason, Integer identity) throws Exception {
        ReturnBean returnBean = new ReturnBean();
        //查看订单中是否存在该订单
        MfflOrder MfflOrder = mfflOrderDao.getBypaymerchantnumber(payMerchantNumber);
        if (MfflOrder == null) {
            returnBean.setReturnBean("106");
            return returnBean;
        }
        if (MfflOrder.getState() == 0) {
            returnBean.setReturnBean("129");
            return returnBean;
        }
        if (MfflOrder.getState() == 2) {
            returnBean.setReturnBean("114");
            return returnBean;
        }

        if (MfflOrder.getState() == 4 && identity == 0) {
            returnBean.setReturnBean("118");
            return returnBean;
        }

        // WechatPay wechatPay = new WechatPay();
        Map<String, String> map = new HashMap<>();
        //微信订单号
        map.put("transaction_id", MfflOrder.getPayNumber());
        //商户退款单号
        map.put("out_refund_no", MfflOrder.getPayNumber());
        //订单金额
        map.put("total_fee", String.valueOf((int) (MfflOrder.getMoney() * 100)));
        //退款金额
        map.put("refund_fee", StringUtils.isEmpty(refundfee) ? String.valueOf((int) (MfflOrder.getMoney() * 100)) : refundfee);
        //回调地址
        // map.put("notify_url","http://lut88.vaiwan.com/client/mfflContracts/weChatrefundNotify");
        //随机数
        map.put("nonce_str", ProjectUtil.getRandom(10));
        //退款理由
        map.put("refund_desc", refundreason);


        try {
            Map map1 = wechatpay.weChatrefund(map);
            if (map1.containsKey("result_code") && map1.get("result_code").equals("SUCCESS")) {
                //修改订单表
                MfflOrder mffd = new MfflOrder();
                mffd.setId(MfflOrder.getId());
                mffd.setDeleteStae(0);
                Date date = new Date();
                mffd.setUpdtaeTime(date);
                mffd.setState(2);
                mfflOrderDao.update(mffd);

                //查询退款表，存在就更新，不存在就创建
                MfflRefund byorderId = mfflRefundDao.getByorderId(MfflOrder.getId());
                //获取当前用户
                SysUser sysUser = UserUtil.getLoginUser();
                if (byorderId == null) {
                    MfflRefund refund = new MfflRefund();
                    refund.setUserid(MfflOrder.getUserid());
                    refund.setImplementid(sysUser == null ? mffd.getUserid() : sysUser.getId().intValue());
                    refund.setOrderid(MfflOrder.getId().intValue());
                    refund.setPaynumber(MfflOrder.getPayNumber());
                    refund.setPaymerchantnumber(MfflOrder.getPayMerchantNumber());
                    refund.setRefundnumber(MfflOrder.getPayNumber());
                    refund.setRefundreason(refundreason);
                    refund.setRefundstate(1);
                    refund.setMoney(MfflOrder.getMoney());
                    refund.setActualamount(MfflOrder.getMoney());
                    refund.setRefundtime(date);
                    refund.setCreateTime(date);
                    refund.setUpdateTime(date);
                    refund.setConfirmrefundtim(date);
                    refund.setRefundname(MfflOrder.getServiceName());
                    mfflRefundDao.save(refund);
                } else {
                    //修改退款订单
                    MfflRefund refund = new MfflRefund();
                    refund.setId(byorderId.getId());
                    refund.setRefundnumber(MfflOrder.getPayNumber());
                    refund.setRefundreason(refundreason);
                    refund.setRefundstate(1);
                    refund.setMoney(MfflOrder.getMoney());
                    refund.setActualamount(MfflOrder.getMoney());
                    refund.setUpdateTime(date);
                    refund.setConfirmrefundtim(date);
                    mfflRefundDao.update(refund);
                }
                returnBean.setDatas(map1);
            } else {
                if (map1.containsKey("err_code_des")) {
                    returnBean.setReturnBean("140");
                    returnBean.setMessage(map1.get("err_code_des").toString());
                    return returnBean;
                } else {
                    returnBean.setReturnBean("140");
                    return returnBean;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            returnBean.setDatas("105");
            return returnBean;
        }
        return returnBean;
    }


    /**
     * 微信查询订单
     *
     * @param payMerchantNumber
     * @return
     */
    public Map orderquery(String payMerchantNumber) {
        Map<String, String> map = new HashMap<>();
        try {
            //查看退款信息
            map = wechatpay.orderquery(new HashMap<String, String>() {{
                put("out_trade_no", payMerchantNumber);
            }});
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return map;
        }
    }

    /**
     * 获取微信支付随机字符串
     * 存放到redis中用于回调时验证，是否为恶意访问回调
     * <p>
     * 结构：Key:Value
     * weixinpay:base64UrlEncode(Key+.+Value)
     *
     * @param payMerchantNumber 随机字符串
     * @return
     */
    public String getNonce_str(String payMerchantNumber) {
        String random = ProjectUtil.getRandom(10);
        //redis缓存
        redisTemplate.boundValueOps(getPayKey(random)).set(payMerchantNumber, payConfirmSeconds, TimeUnit.SECONDS);
        return random;
    }

    private String getPayKey(String uuid) {
        return "payMerchantNumber:" + uuid;
    }


    /**
     * 验证微信发送回来的随机数
     */
    public boolean VerificationWeChatCallback(String Nonce_str) {
        String nonceStr = redisTemplate.opsForValue().get(getPayKey(Nonce_str));
        System.out.println(nonceStr + "----******");
        if (nonceStr == null) {
            return false;
        } else {
            return true;
        }
    }


    /**
     * 处理微信回调数据
     *
     * @param request
     * @return
     * @throws Exception
     */
    public Map<String, String> WechatPayCallback(HttpServletRequest request) throws Exception {
        //获取字节流
        InputStream inputstream = request.getInputStream();
        StringBuffer sb = new StringBuffer();
        String s;
        //字节流转字符流，通过高速字符流缓冲区读取
        BufferedReader in = new BufferedReader(new InputStreamReader(inputstream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputstream.close();

        //处理微信支付返回的数据
        OurWxPayConfig ourWXPayConfig = new OurWxPayConfig();
        WXPay wxpay = new WXPay(ourWXPayConfig);
        Map<String, String> returnmap = wxpay.processResponseXml(sb.toString());
        return returnmap;
    }

    /**
     * 返回微信需要的数据
     *
     * @param state
     * @return
     */
    public String WechatPayCallbackReturnData(boolean state) throws Exception {
        //通知给微信支付系统订单已完成
        Map<String, String> noticeData = new HashMap<String, String>();
        if (state) {
            noticeData.put("return_code", "SUCCESS");
            noticeData.put("return_msg", "OK");
            String noticeDataString = WXPayUtil.mapToXml(noticeData);
            return noticeDataString;
        } else {
            noticeData.put("return_code", "ERROR");
            noticeData.put("return_msg", "no");
            String noticeDataString = WXPayUtil.mapToXml(noticeData);
            return noticeDataString;
        }
    }
}
